iT邦幫忙

1

PowerShell查看藍牙耳機的電量

  • 分享至 

  • xImage
  •  

查看藍牙耳機的電量

# 不知道耳機名稱。列出所有藍牙設備
Get-PnpDevice -class system | where service -eq BthHFEnum

# 藍牙耳機的電量
$name = 'sound'
$a = Get-PnpDevice -class system -FriendlyName "*$name*" | Get-PnpDeviceProperty  -KeyName '{104EA319-6EE2-4701-BD47-8DDBF425BBE5} 2'
$a.Data

# 配對的時間(第一次配對or刪除配對資料、重新配對)
$name = 'sound'
$a = Get-PnpDevice -class system -FriendlyName "*$name*" | Get-PnpDeviceProperty -KeyName 'DEVPKEY_Device_InstallDate'
$a.Data

# 連線到電腦的時間
$name = 'sound'
$a = Get-PnpDevice -class system -FriendlyName "*$name*" | Get-PnpDeviceProperty -KeyName 'DEVPKEY_Device_LastArrivalDate'
$a.Data

# 電腦藍牙狀態(開啟or關閉)。不是藍牙耳機有沒有連線
# DEVPKEY_Device_IsPresent

查看藍牙耳機的電量 by WinRT

Win10以上適用

藍牙有兩種:傳統藍牙、低功耗藍牙
這是用來查看傳統藍牙藍牙耳機的電量

之前使用python的bleak模組,想要掃描自己的藍牙耳機
但是,沒有找到。
倒是有找到別人的LE_WF-1000XM4Xiaomi Band 8 Active 2D11Xiaomi Smart Band 8 2ADC
如今赫然發現
Bleak is an acronym for Bluetooth Low Energy platform Agnostic Klient.

  1. 修改第一行,設定$name的值為藍牙耳機名稱
  2. 載入WindowsRuntime

Add-Type -AssemblyName System.Runtime.WindowsRuntime

  1. 定義 await 函數
  2. 載入名稱空間的其中一個類別,以使用名稱空間的所有類別

[類別, 名稱空間, ContentType=WindowsRuntime]
[Windows.Devices.Bluetooth.BluetoothDevice, Windows.Devices.Bluetooth, ContentType=WindowsRuntime] > $null

  1. 使用 await 函數
    如果不使用await函數,物件方法傳回值PowerShell不認得,
    變成System.__ComObject,沒有可用的屬性、方法
  2. await函數的使用方法
    await (方法名) (參數) (參數) (參數)
    方法名後面,不要加括弧。也就是,不要去執行方法。
    用小括弧把方法名參數圍起來
    如果方法名參數是變數,可以不用圍起來
    參數與參數之間,以空格分隔。不要用逗號。
$name = 'sound'

Add-Type -AssemblyName System.Runtime.WindowsRuntime

# learn from https://fleexlab.blogspot.com/2018/02/using-winrts-iasyncoperation-in.html
# leran from https://superuser.com/questions/1168551/turn-on-off-bluetooth-radio-adapter-from-cmd-powershell-in-windows-10
Function await($method) {
    $IAsyncT = $null

    if ($method.ReturnType){
        $IAsyncT = $method.ReturnType
        $WinRtTask = $method.Invoke($args[0], $args[1..100])
        <#
        $socket = [Windows.Networking.Sockets.StreamSocket]::new()
        $socket.InputStream is System.__ComObject
        can't use $socket.InputStream.ReadAsync method

        $readMethod = [Windows.Storage.Streams.IInputStream].GetDeclaredMethod('ReadAsync')

        use await function
            error
                await $readMethod $socket.InputStream $buffer [uint32]1KB [Windows.Storage.Streams.InputStreamOptions]::Partial
            ok
                await $readMethod $socket.InputStream $buffer ([uint32]1KB) ([Windows.Storage.Streams.InputStreamOptions]::Partial)
                    or
                $a = [uint32]1KB
                $b = [Windows.Storage.Streams.InputStreamOptions]::Partial
                await $readMethod $socket.InputStream $buffer $a $b

        in await function
            $method
                $readMethod
            $args[0]
                $socket.InputStream
            $args[1..100]
                $buffer, $a, $b
        #>
    }elseif($method.OverloadDefinitions[0] -match "(Windows.Foundation.IAsync.*) $($method.Name)"){
        $IAsyncT = [type]$Matches[1]
        $WinRtTask = $method.Invoke($args)
        <#
        use await function
            error
                await [Windows.Storage.StorageFile]::GetFileFromPathAsync('C:\1.txt')
                await [Windows.Storage.StorageFile]::GetFileFromPathAsync 'C:\1.txt'
            ok
                await ([Windows.Storage.StorageFile]::GetFileFromPathAsync) 'C:\1.txt'
                    or
                $a = [Windows.Storage.StorageFile]::GetFileFromPathAsync
                await $a 'C:\1.txt'

        in await function
            $method
                [Windows.Storage.StorageFile]::GetFileFromPathAsync
            $method.OverloadDefinitions[0]
                  static Windows.Foundation.IAsyncOperation[Windows.Storage.StorageFile] GetFileFromPathAsync(string path)
            $args
                @('C:\1.txt')
        #>
    }else{
        throw 'method error'
    }

    $asTask = [System.WindowsRuntimeSystemExtensions].GetMethods() | where {
        $_.Name -eq 'AsTask' -and
        $IAsyncT.Name -eq $_.GetParameters().ParameterType.name
    }

    $ResultType = $IAsyncT.GenericTypeArguments
    if ($ResultType.Count -gt 0){
        $asTask = $asTask.MakeGenericMethod($ResultType)
    }

    $netTask = $asTask.Invoke($null, @($WinRtTask))
    $netTask.Wait(-1) | Out-Null

    if ($IAsyncT.Name -like 'IAsyncOperation*'){
        return $netTask.Result
    }
}

[Windows.Devices.Radios.Radio, Windows.System.Devices, ContentType=WindowsRuntime] > $null
[Windows.Devices.Bluetooth.BluetoothDevice, Windows.Devices.Bluetooth, ContentType=WindowsRuntime] > $null
[Windows.Devices.Enumeration.DeviceInformation, Windows.Devices.Enumeration, ContentType=WindowsRuntime] > $null
[Windows.Storage.Streams.Buffer, Windows.Storage.Streams, ContentType=WindowsRuntime] > $null

<#
# Turn on Bluetooth adapter
$r = await ([Windows.Devices.Radios.Radio]::RequestAccessAsync)
if ($r -eq 'Allowed'){
    $radios = await ([Windows.Devices.Radios.Radio]::GetRadiosAsync)
    $bluetooth = $radios | where Kind -eq 'Bluetooth'
    if ($bluetooth.State -ne 'On'){
        # on   off
        await $bluetooth.SetStateAsync 'on' > $null
    }
}
#>

$q = [Windows.Devices.Bluetooth.BluetoothDevice]::GetDeviceSelectorFromPairingState($true)
$arr = await ([Windows.Devices.Enumeration.DeviceInformation]::FindAllAsync) $q
$deviceId = $arr | where Name -like "*$name*" | select -expand Id
$BluetoothDevice = await ([Windows.Devices.Bluetooth.BluetoothDevice]::FromIdAsync) $deviceId
<#
$deviceId = Get-PnpDevice -FriendlyName "*$name*" -class system | Get-PnpDeviceProperty -KeyName '{3B2CE006-5E61-4FDE-BAB8-9B8AAC9B26DF} 8' | select  -ExpandProperty data
$BluetoothDevice = await ([Windows.Devices.Bluetooth.BluetoothDevice]::FromIdAsync) $deviceId
# $BluetoothDevice.ConnectionStatus
#>

$r = await $BluetoothDevice.GetRfcommServicesAsync
# HeadsetServiceClass_UUID {00001108-0000-1000-8000-00805F9B34FB}
$service = $r.Services | where ConnectionServiceName -like '*{00001108*'


$socket = [Windows.Networking.Sockets.StreamSocket]::new()

while($true){
    try{
        await $socket.ConnectAsync $service.ConnectionHostName $service.ConnectionServiceName
    }catch{
        continue
    }
    break
}

$buffer = [Windows.Storage.Streams.Buffer]::new(1KB)
$readMethod = [Windows.Storage.Streams.IInputStream].GetDeclaredMethod('ReadAsync')

$output = ''
while ($output -notlike '*IPHONEACCEV*'){
    $result = await $readMethod $socket.InputStream $buffer ([uint32]1KB) ([Windows.Storage.Streams.InputStreamOptions]::Partial)

    $reader = [Windows.Storage.Streams.DataReader]::FromBuffer($result)
    $output = $reader.ReadString($result.Length)
    echo $output
}

<#
AT+IPHONEACCEV=2,1,7,2,0
AT+IPHONEACCEV=(Number of key/value pairs),key1,val1,key2,val2,...
key
    1 = Battery Level
    2 = Dock State
value
    Battery Level: string value between '0' and '9'
    Dock State: 0 = undocked, 1 = docked
#>
$arr = ($output -split '=')[1] -split ','
$n, $arr = $arr

while ($null -ne $arr){
    $a, $b, $arr = $arr
    if ($a -eq '1'){
        echo ""
        echo "battery:$(1+$b)0%"
        break
    }
}

$socket.Dispose()
Pause

只能查看主耳機的電量

TheWeirdDev/Bluetooth_Headset_Battery_Level · GitHub
這個連結有提到用Google Fast Pair 去查看左耳、右耳的電量

藍牙耳機的煩惱

  • 配對
  • 電量

充電盒的功能

  • 充電
  • 配對

藍牙耳機的狀態

  • 指示燈
  • 音效

第一次配對的兩種方式

  1. 設定 → 藍牙與裝置 → 新增裝置
  2. Win10 Swift 配對
    藍牙耳機靠近電腦時,螢幕右下角出現配對畫面

其中一耳電量偏低

放回充電盒、接觸不良、沒有充到電
如果那一耳是主耳機,放回充電盒、有在充電的話,會中斷藍牙連線

參考資料


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
jianfengvs
iT邦新手 5 級 ‧ 2024-09-19 11:10:41

挺好的

我要留言

立即登入留言